var Window=function(conf){
	var winHtml, defaults = { modal:true, renderCloser: true, title:'' }, self = this;
	this.conf = {};
	$.extend(this.conf, defaults, conf);
	
	winHtml = '<div class="window '+(this.conf.cls||'')+'">';
	if (this.conf.renderCloser) winHtml += '<div href="#" title="Close window" class="window-closer"></div>';

	winHtml += '<div class="window-title"></div><div class="window-content"></div></div>';
	this.el = $(winHtml).hide(); 
	$('body').append(this.el); 

	this.el.click(function(e){ e.stopPropagation(); });
	this.el.draggable({ containment: 'body', handle :'.window-title' });
	
	this.title = this.el.find('.window-title');			// $ el - window title
	this.content = this.el.find('.window-content');		// $ el - window content
	this.windowCloser = this.el.find('.window-closer');	// $ el - window closer
	
	
	if (typeof this.conf.content == 'object' && this.conf.content.length){
		this.content.append(this.conf.content);
		this.conf.content.css('display','');
		var data = this.conf.content.data();
		if (data && data.width) this.el.width(data.width||'auto');
		
		if (!this.conf.title.length && this.conf.content.length){
			this.conf.title = this.conf.content.attr('title');
			this.conf.content.removeAttr('title');
		}
	} 
	else if (typeof this.conf.content == 'string') this.content.html(this.conf.content);
	
	this.title.html(this.conf.title);
	
	this.windowCloser.unbind('click').bind('click', function(){ self.hide.call(self); return false; });
	
	// Add buttons
	if (this.conf.buttons && this.conf.buttons.length>0){
		var i=0
			,bl = this.conf.buttons.length
			,buttons			// $ html object of buttons
			,btnConf			// temp config button
			,btn;				// temp button $ object

		buttons = $('<div class="buttons"></div>');
		
		for (; i<bl; i++){
			btnConf = this.conf.buttons[i];
			btn = $('<button class="button">'+btnConf.text+'</button>');
			if (btnConf.cls) btn.addClass(btnConf.cls);
			if (btnConf.disabled == true) btn.attr('disabled', 'disabled').addClass('disabled');
			if (!btnConf.scope) btnConf.scope = this.content;
			
			if (!btnConf.fn) btn.bind('click', $.proxy(this.hide, this));
			else {
				btn.bind('click', { content: this.content, btn: btnConf, win: this }, function(e){
					var conf = e.data.btn, win = e.data.win, content = e.data.content;
					if (conf.fn.call(conf.scope, content) !== false) win.hide.call(win);
				});
			}
			
			
			buttons.append(btn);		// append button to the buttons element
		}
		this.content.append(buttons);	// append buttons to the window content
	}
	return this;
};


/**
 * Shows the window. 
 */
Window.prototype.show = function(){
	if (!this.el) return;
	if (this.conf.modal) this.maskShow(); 
	$(window).bind({ resize: $.proxy(this.center, this) });
	if (this.conf.closable !== false) $(window).bind({ keydown: $.proxy(this.onEscape, this) });		// if closable - close on ESC
	this.center();
	this.el.show().animate({ opacity: 1 }, 'fast', 'swing', function(){ $(this).find('input:visible:first').focus(); try{$(this).find('input:visible')[0].select();}catch(e){} });
	return this;
};


/**
 * Hides the window component
 */
Window.prototype.hide = function(){
	var self = this;
	if (this.conf.onClose) this.conf.onClose.fn.call(this.conf.onClose.scope);
	if (this.el && this.el.is(":visible")){
		if (this.el) this.el.animate({ opacity: 0 }, 'fast', 'swing', function(){ if (self.conf.disposable) $(this).remove(); else $(this).hide(); });
		if (this.mask) this.maskHide();
		$(window).unbind('resize', this.center).unbind('keydown', this.onEscape);
	}
	return this;
};


/**
 * Adds a keydown event. Hit esc to close the window 
 */
Window.prototype.onEscape = function(e){ if(e.keyCode==27) this.hide(); };



/**
 * Center the window on screen
 */
Window.prototype.center = function(){
	var l=($('body').innerWidth()/2)-(this.el.outerWidth()/2), t=($('html').innerHeight()/2)-(this.el.outerHeight()/2);
	this.el.css({ left: l<0?l=0:l, top: t<0?t=0:t });
	return this;
};



/**
 * Shows the mask under the window (if modal==true)
 */
Window.prototype.maskShow = function(){ 
	this.mask=$('#mask');
	if (!this.mask.length){ 
		this.mask=$('<div id="mask"></div>'); 
		$('body').append(this.mask); 
		var self=this; 
		if (this.conf.closable !== false) this.mask.click(function(){self.hide.call(self,true);}); 
	}
	this.mask.animate({ opacity: 0.7 }, 'fast');			
};	


Window.prototype.maskHide = function(){ var self=this; if (this.mask) this.mask.animate({ opacity: 0}, 'fast', function(){self.mask.remove();}); };
